home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / b / b.lha / B / src / bed / bobj.c < prev    next >
C/C++ Source or Header  |  1988-11-24  |  10KB  |  646 lines

  1. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
  2. static char rcsid[] = "$Header: bobj.c,v 2.5 85/08/22 15:59:59 timo Exp $";
  3.  
  4. /*
  5.  * B editor -- A shrunken version of the B interpreter's run-time system.
  6.  */
  7.  
  8. #include "b.h"
  9. #include "bobj.h"
  10. #include "node.h"
  11.  
  12. #define COMPOUNDS
  13.  
  14. string malloc();
  15. string calloc();
  16. string realloc();
  17. string strcpy();
  18.  
  19. extern bool dflag;
  20.  
  21. struct head {
  22.     char type;
  23.     intlet refcnt;
  24.     intlet len;
  25. };
  26. #define Intsize (sizeof(int))
  27. #define Hsize (sizeof(struct head))
  28. #define Headsize (((Hsize-1)/Intsize + 1) * Intsize)
  29.  
  30. #define Field(v, i) (((value *)&(v)->cts)[i])
  31.  
  32. #ifndef NDEBUG
  33.  
  34. /* Statistics on allocation/sharing */
  35.  
  36. int nobjs;
  37. int nrefs;
  38.  
  39. #define Increfs ++nrefs
  40. #define Decrefs --nrefs
  41.  
  42. #else NDEBUG
  43.  
  44. #define Increfs 
  45. #define Decrefs 
  46.  
  47. #endif NDEBUG
  48.  
  49.  
  50. #define Copy(v) if ((v) && Refcnt(v) < Maxintlet) { ++Refcnt(v); Increfs; }
  51. #define Release(v) if (!(v) || Refcnt(v) == Maxintlet) ; else RRelease(v)
  52. #define RRelease(v) \
  53.     if (Refcnt(v) > 1) { --Refcnt(v); Decrefs; } else release(v)
  54.  
  55.  
  56. /*
  57.  * Allocate a value with nbytes of data after the usual type, len, refcnt
  58.  * fields.
  59.  */
  60.  
  61. value
  62. grabber(nbytes)
  63.     register int nbytes;
  64. {
  65.     register value v = (value) malloc((unsigned) (Headsize + nbytes));
  66.  
  67.     if (!v)
  68.         syserr("grabber: malloc");
  69. #ifndef NDEBUG
  70.     if (dflag)
  71.         newval(v);
  72. #endif
  73. #ifndef NDEBUG
  74.     ++nobjs;
  75. #endif
  76.     Increfs;
  77.     v->refcnt = 1;
  78.     return v;
  79. }
  80.  
  81.  
  82. /*
  83.  * Reallocate a value with nbytes of data after the usual type, len, refcnt
  84.  * fields.
  85.  */
  86.  
  87. value
  88. regrabber(v, nbytes)
  89.     register value v;
  90.     register int nbytes;
  91. {
  92.     Assert(v && v->refcnt == 1);
  93.     v = (value) realloc((char*)v, (unsigned) (Headsize + nbytes));
  94.     if (!v)
  95.         syserr("regrabber: realloc");
  96.     return v;
  97. }
  98.  
  99.  
  100. /*
  101.  * Set an object's refcnt to infinity, so it will never be released.
  102.  */
  103.  
  104. fix(v)
  105.     register value v;
  106. {
  107.     register int i;
  108.     register node n;
  109.     register path p;
  110.  
  111.     Assert(v->refcnt > 0);
  112. #ifndef NDEBUG
  113.     if (v->refcnt < Maxintlet)
  114.         nrefs -= v->refcnt;
  115. #endif
  116.     v->refcnt = Maxintlet;
  117. #if OBSOLETE
  118.     switch (v->type) {
  119.     case Tex:
  120.         break;
  121.     case Nod:
  122.         n = (node)v;
  123.         for (i = v->len - 1; i >= 0; --i)
  124.             if (n->n_child[i])
  125.                 fix((value)(n->n_child[i]));
  126.         break;
  127.     case Pat:
  128.         p = (path)v;
  129.         if (p->p_parent)
  130.             fix((value)(p->p_parent));
  131.         if (p->p_tree)
  132.             fix((value)(p->p_tree));
  133.         break;
  134. #ifdef COMPOUNDS
  135.     case Com:
  136.         for (i = v->len-1; i >= 0; --i)
  137.             if (Field(v, i))
  138.                 fix(Field(v, i));
  139.         break;
  140. #endif COMPOUNDS
  141. #ifdef SLOW_INTS
  142.     case Num:
  143. #endif SLOW_INTS
  144.     default:
  145.         Abort();
  146.     }
  147. #endif OBSOLETE
  148. }
  149.  
  150.  
  151. #ifdef COMPOUNDS
  152. /*
  153.  * Allocate a compound with n fields.
  154.  */
  155.  
  156. Visible value
  157. grab_com(n)
  158.     int n;
  159. {
  160.     value v = grabber(n*sizeof(value));
  161.  
  162.     v->type = Com;
  163.     v->len = n;
  164.     for (--n; n >= 0; --n)
  165.         Field(v, n) = Vnil;
  166.     return v;
  167. }
  168. #endif COMPOUNDS
  169.  
  170.  
  171. /*
  172.  * Allocate a node with nch children.
  173.  */
  174.  
  175. node
  176. grab_node(nch)
  177.     register int nch;
  178. {
  179.     register node n = (node) grabber(
  180.             sizeof(struct node) - Headsize +
  181.             sizeof(value) * (nch-1));
  182.     register int i;
  183.  
  184.     n->type = Nod;
  185.     n->len = nch;
  186.     n->n_marks = 0;
  187.     n->n_width = 0;
  188.     n->n_symbol = 0;
  189.     for (i = nch-1; i >= 0; --i)
  190.         n->n_child[i] = Nnil;
  191.     return n;
  192. }
  193.  
  194.  
  195. /*
  196.  * Allocate a path.
  197.  */
  198.  
  199. path
  200. grab_path()
  201. {
  202.     register path p = (path) grabber(
  203.             sizeof(struct path) - Headsize);
  204.  
  205.     p->type = Pat;
  206.     p->p_parent = Pnil;
  207.     p->p_tree = Nnil;
  208.     p->p_ichild = 0;
  209.     p->p_ycoord = 0;
  210.     p->p_xcoord = 0;
  211.     p->p_level = 0;
  212.     p->p_addmarks = 0;
  213.     p->p_delmarks = 0;
  214.     return p;
  215. }
  216.  
  217.  
  218. #ifdef SLOW_INTS
  219. /*
  220.  * Make an integer.
  221.  */
  222.  
  223. value
  224. mk_integer(i)
  225.     int i;
  226. {
  227.     value v;
  228.     static value tab[128];
  229.  
  230.     if (!i)
  231.         return Vnil;
  232.     if (!(i&~127) && tab[i])
  233.         return tab[i];
  234.  
  235.     v = grabber(sizeof(value));
  236.     v->type = Num;
  237.     Field(v, 0) = (value) i;
  238.     if (!(i&~127)) {
  239.         tab[i] = v;
  240.         v->refcnt = Maxintlet;
  241.     }
  242.     return v;
  243. }
  244. #endif SLOW_INTS
  245.  
  246.  
  247. /*
  248.  * Make a text object out of a C string.
  249.  */
  250.  
  251. value
  252. mk_text(str)
  253.     register string str;
  254. {
  255.     register int len = strlen(str);
  256.     register value v = grabber(len+1);
  257.  
  258.     v->type = Tex;
  259.     v->len = len;
  260.     strcpy(Str(v), str);
  261.     return v;
  262. }
  263.  
  264.  
  265. /*
  266.  * Concatenate a C string to a text object (at the end).
  267.  */
  268.  
  269. concato(pv, str)
  270.     register value *pv;
  271.     register string str;
  272. {
  273.     register value v = *pv;
  274.     register int vlen = v->len;
  275.     register int len = strlen(str);
  276.  
  277.     Assert(v && v->refcnt > 0);
  278.     if (!len)
  279.         return;
  280.  
  281.     len += vlen;
  282.     if (v->refcnt == 1)
  283.         v = regrabber(v, len+1);
  284.     else {
  285.         v = grabber(len+1);
  286.         v->type = Tex;
  287.         strcpy(Str(v), Str(*pv));
  288.         Release(*pv);
  289.     }
  290.     strcpy(Str(v) + vlen, str);
  291.     v->len = len;
  292.     *pv = v;
  293. }
  294.  
  295.  
  296. /*
  297.  * Return a substring (trim) of a text object.
  298.  */
  299.  
  300. value
  301. trim(v, behead, curtail)
  302.     register value v;
  303.     register int behead;
  304.     register int curtail;
  305. {
  306.     register value w;
  307.     register int c;
  308.  
  309.     Assert(v && v->refcnt > 0);
  310.     Assert(behead >= 0 && curtail >= 0 && behead+curtail <= v->len);
  311.     if (behead + curtail == 0) {
  312.         Copy(v);
  313.         return v;
  314.     }
  315.  
  316.     c = Str(v)[v->len - curtail];
  317.     Str(v)[v->len - curtail] = 0; /* TEMPORARILY */
  318.     w = mk_text(Str(v) + behead);
  319.     Str(v)[v->len - curtail] = c;
  320.     return w;
  321. }
  322.  
  323.  
  324. #ifdef SLOW_INTS
  325. /*
  326.  * Return the C value if an integer object.
  327.  */
  328.  
  329. int
  330. intval(v)
  331.     register value v;
  332. {
  333.     if (!v)
  334.         return 0;
  335.     return (int) Field(v, 0);
  336. }
  337. #endif SLOW_INTS
  338.  
  339.  
  340. /*
  341.  * Make sure a location (pointer variable) contains a unique object.
  342.  */
  343.  
  344. uniql(pv)
  345.     register value *pv;
  346. {
  347.     register value v = *pv;
  348.     register value w;
  349.     register path p;
  350.     register node n;
  351.     register int i;
  352.  
  353.     Assert(v && v->refcnt > 0);
  354.     if (v->refcnt == 1)
  355.         return;
  356.  
  357.     switch (v->type) {
  358.  
  359.     case Nod:
  360.         n = grab_node(v->len);
  361.         for (i = v->len - 1; i >= 0; --i) {
  362.             w = (value) (n->n_child[i] = ((node)v)->n_child[i]);
  363.             Copy(w); /* This is ugly */
  364.         }
  365.         n->n_marks = ((node)v)->n_marks;
  366.         n->n_width = ((node)v)->n_width;
  367.         n->n_symbol = ((node)v)->n_symbol;
  368.         w = (value)n;
  369.         break;
  370.  
  371.     case Pat:
  372.         p = grab_path();
  373.         p->p_parent = ((path)v)->p_parent;
  374.         Copy(p->p_parent);
  375.         p->p_tree = ((path)v)->p_tree;
  376.         Copy(p->p_tree);
  377.         p->p_ichild = ((path)v)->p_ichild;
  378.         p->p_ycoord = ((path)v)->p_ycoord;
  379.         p->p_xcoord = ((path)v)->p_xcoord;
  380.         p->p_level = ((path)v)->p_level;
  381.         w = (value)p;
  382.         break;
  383.  
  384. #ifdef SLOW_INTS
  385.     case Num:
  386.         w = mk_integer(intval(v));
  387.         break;
  388. #endif SLOW_INTS
  389.  
  390. #ifdef COMPOUNDS
  391.     case Com:
  392.         w = grab_com(v->len);
  393.         for (i = v->len - 1; i >= 0; --i) {
  394.             n = (node) (Field(w, i) = Field(v, i));
  395.             Copy(n); /* This is uglier */
  396.         }
  397.         break;
  398. #endif COMPOUNDS
  399.  
  400.     case Tex:
  401.         w = mk_text(Str(v));
  402.         break;
  403.  
  404.     default:
  405.         Abort();
  406.  
  407.     }
  408.     Release(v);
  409.     *pv = w;
  410. }
  411.  
  412.  
  413. /*
  414.  * Increase the reference count of an object, unless it is infinite.
  415.  */
  416.  
  417. value
  418. copy(v)
  419.     value v;
  420. {
  421.     if (!v)
  422.         return v;
  423.  
  424.     Assert(v->refcnt > 0);
  425.     if (v->refcnt < Maxintlet) {
  426.         ++v->refcnt;
  427.         Increfs;
  428.     }
  429.     return v;
  430. }
  431.  
  432.  
  433. /*
  434.  * Decrease the reference count of an object, unless it is infinite.
  435.  * If it reaches zero, free the storage occupied by the object.
  436.  */
  437.  
  438. release(v)
  439.     register value v;
  440. {
  441.     register int i;
  442.     register value w;
  443.  
  444.     if (!v)
  445.         return;
  446.     Assert(v->refcnt > 0);
  447.     if (v->refcnt == Maxintlet)
  448.         return;
  449.  
  450.     Decrefs;
  451.     --v->refcnt;
  452.     if (v->refcnt == 0) {
  453.         switch (v->type) {
  454. #ifdef SLOW_INTS
  455.         case Num:
  456. #endif SLOW_INTS
  457.         case Tex:
  458.             break;
  459. #ifdef COMPOUNDS
  460.         case Com:
  461.             for (i = v->len - 1; i >= 0; --i) {
  462.                 w = Field(v, i);
  463.                 Release(w);
  464.             }
  465.             break;
  466. #endif COMPOUNDS
  467.         case Nod:
  468.             for (i = v->len - 1; i >= 0; --i) {
  469.                 w = (value)(((node)v)->n_child[i]);
  470.                 Release(w);
  471.             }
  472.             break;
  473.         case Pat:
  474.             w = (value)(((path)v)->p_parent);
  475.             Release(w);
  476.             w = (value)(((path)v)->p_tree);
  477.             Release(w);
  478.             break;
  479.         default:
  480.             Abort();
  481.         }
  482. #ifndef NDEBUG
  483.         if (dflag)
  484.             delval(v);
  485.         --nobjs;
  486. #endif NDEBUG
  487.         free((string)v);
  488.     }
  489. }
  490.  
  491. objstats()
  492. {
  493. #ifndef NDEBUG
  494.     fprintf(stderr, "*** Object statistics: %d objects, %d references\n",
  495.         nobjs, nrefs);
  496. #ifdef MSTATS
  497.     mstats("(at end)"); /* A routine which some malloc versions have to print
  498.                  memory statistics. Remove if your malloc hasn't. */
  499. #endif MSTATS
  500. #endif NDEBUG
  501. }
  502.  
  503. #ifndef NDEBUG
  504. valdump(v)
  505.     value v;
  506. {
  507.     if (!v)
  508.         fputs("(nil)", stderr);
  509.     else {
  510.         fprintf(stderr, "v=0x%x, type='%c', len=%d, refcnt=",
  511.             v, v->type, v->len);
  512.         if (v->refcnt == Maxintlet)
  513.             putc('*', stderr);
  514.         else
  515.             fprintf(stderr, "%d", v->refcnt);
  516.         fputs(": ", stderr);
  517.         wrval(v);
  518.  
  519.     }
  520.     putc('\n', stderr);
  521. }
  522.  
  523. #define QUOTE '\''
  524.  
  525. wrval(v)
  526.     value v;
  527. {
  528.     register string cp;
  529.     register int c;
  530.  
  531.     if (!v) {
  532.         fputs("nil", stderr);
  533.         return;
  534.     }
  535.  
  536.     switch (v->type) {
  537.  
  538. #ifdef SLOW_INTS
  539.     case Num:
  540.         fprintf(stderr, "%d", intval(v));
  541.         break;
  542. #endif SLOW_INTS
  543.  
  544.     case Tex:
  545.         putc(QUOTE, stderr);
  546.         for (cp = Str(v); c = *cp; ++cp) {
  547.             if (' ' <= c && c < 0177) {
  548.                 putc(c, stderr);
  549.                 if (c == QUOTE)
  550.                     putc(c, stderr);
  551.             }
  552.             else if (0 <= c && c < ' ')
  553.                 putc('^', stderr), putc(c + '@', stderr);
  554.             else
  555.                 fprintf(stderr, "\\%03o", c);
  556.         }
  557.         putc(QUOTE, stderr);
  558.         break;
  559.  
  560. #ifdef COMPOUNDS
  561.     case Com:
  562.       {
  563.           int i;
  564.         value f;
  565.         putc('(', stderr);
  566.         for (i = 0; i < v->len; ++i) {
  567.             if (i)
  568.                 putc(',', stderr), putc(' ', stderr);
  569.             f = Field(v, i);
  570.             if (!f || f->refcnt == 1 || f->type != Com) {
  571.                 if (f && f->type == Com)
  572.                     fprintf(stderr, "0x%x=", f);
  573.                 wrval(f);
  574.             }
  575.             else
  576.                 fprintf(stderr, "0x%x", f);
  577.         }
  578.         putc(')', stderr);
  579.         break;
  580.       }
  581. #endif COMPOUNDS
  582.  
  583.     default:
  584.         fprintf(stderr, "0x%x", v);
  585.  
  586.     }
  587. }
  588.  
  589. static struct list {
  590.     struct list *link;
  591.     value val;
  592. } head;
  593. #endif NDEBUG
  594.  
  595. objdump()
  596. {
  597. #ifndef NDEBUG
  598.     struct list *l;
  599.  
  600.     for (l = head.link; l; l = l->link)
  601.         valdump(l->val);
  602. #endif NDEBUG
  603. }
  604.  
  605. objcheck()
  606. {
  607. #ifndef NDEBUG
  608.     struct list *l;
  609.  
  610.     for (l = head.link; l; l = l->link)
  611.         if (l->val->refcnt != Maxintlet)
  612.             valdump(l->val);
  613. #endif NDEBUG
  614. }
  615.  
  616. #ifndef NDEBUG
  617. newval(v)
  618.     register value v;
  619. {
  620.     register struct list *l =
  621.             (struct list *) malloc((unsigned) sizeof(struct list));
  622.  
  623.     if (!l)
  624.         syserr("newval: malloc");
  625.     l->link = head.link;
  626.     l->val = v;
  627.     head.link = l;
  628. }
  629.  
  630. delval(v)
  631.     register value v;
  632. {
  633.     register struct list *l;
  634.     register struct list *p;
  635.  
  636.     for (p = &head, l = head.link; l; p = l, l = l->link) {
  637.         if (l->val == v) {
  638.             p->link = l->link;
  639.             free((string)l);
  640.             return;
  641.         }
  642.     }
  643.     Abort();
  644. }
  645. #endif NDEBUG
  646.